package com.ifast.news.service.impl;

import java.io.IOException;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.mts.model.v20140618.QueryJobListRequest;
import com.aliyuncs.mts.model.v20140618.QueryJobListResponse;
import com.aliyuncs.mts.model.v20140618.QueryJobListResponse.Job;
import com.aliyuncs.mts.model.v20140618.SubmitJobsRequest;
import com.aliyuncs.mts.model.v20140618.SubmitJobsResponse;
import com.aliyuncs.mts.model.v20140618.SubmitJobsResponse.JobResult;
import com.aliyuncs.mts.model.v20140618.SubmitSnapshotJobRequest;
import com.aliyuncs.mts.model.v20140618.SubmitSnapshotJobResponse;
import com.aliyuncs.mts.model.v20140618.SubmitSnapshotJobResponse.SnapshotJob;
import com.baomidou.mybatisplus.enums.SqlLike;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ifast.common.domain.DictDO;
import com.ifast.common.service.DictService;
import com.ifast.common.utils.Const;
import com.ifast.common.utils.alioss.OSSBjOtherClientUtil;
import com.ifast.common.utils.alioss.OSSMtsUtil;
import com.ifast.common.utils.alioss.UploadResult;
import com.ifast.common.utils.alioss.UploadUtils;
import com.ifast.news.dao.NewsCollectDao;
import com.ifast.news.dao.NewsDao;
import com.ifast.news.domain.News;
import com.ifast.news.domain.NewsCollect;
import com.ifast.news.service.NewsService;
import com.ifast.sys.domain.DeptDO;
import com.ifast.sys.service.DeptService;
import com.luculent.util.extension.api.PageResult;
import com.luculent.util.extension.api.Result;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * @author ShiQiang
 * @date 2019年4月9日09:56:53
 */
@Slf4j
@Transactional
@Service("newsService")
public class NewsServiceImpl extends ServiceImpl<NewsDao, News> implements NewsService{
	
	@Value("${httpPath}")
    private String httpPath;
	
	@Autowired
	private NewsCollectDao collectMapper;
	
	@Autowired
    private DictService sysDictService;
	
	@Autowired
    private DeptService sysDeptService;
	
	@Override
	public PageResult<?> pageCollectList(String userId, String dwCode, String nian,
			String yue, String ri, Page<NewsCollect> page) {
		
		if(StringUtils.isBlank(userId) || StringUtils.isBlank(dwCode))
			return PageResult.fail_msg("缺少必要参数");
		
		NewsCollect collect = NewsCollect.builder().userId(userId).build(); 
		if(StringUtils.isNotBlank(nian)){
			collect.setNian(Integer.valueOf(nian));
		}
		if(StringUtils.isNotBlank(yue)){
			collect.setYue(Integer.valueOf(yue));
		}
		if(StringUtils.isNotBlank(ri)){
			collect.setRi(Integer.valueOf(ri));
		} 
		
		return dataCollect2Page(collectMapper.select(page,collect),page);
	}
	/**
	 * 将查询的信息 进行拼装
	 * */
	private  PageResult<?> dataCollect2Page(List<NewsCollect> collects,Page<NewsCollect> pageAll){
		PageResult<Map<String,Object>> pageRes = new PageResult<>(); 
		if(CollectionUtil.isEmpty(collects)){ 
			pageRes.setPageNum(1);
			pageRes.setHasNext(false);
	        return pageRes;
	    } 
		List<Map<String,Object>> listMap = Lists.newArrayList();
		collects.stream().forEach(version ->{  
			Map<String,Object> map = BeanUtil.beanToMap(version);
			map.put("collectId",version.getId());
			listMap.add(map);
		});
		pageRes.setListData(listMap);
		pageRes.setPageNum(pageAll.getCurrent());
		pageRes.setHasNext(pageAll.hasNext());
		return pageRes; 
	}
	
	@Override
	public Result<?> classify(String userId) {
		List<DictDO> dicts = sysDictService.selectList(new EntityWrapper<DictDO>().eq("DELFLAG",0).eq("PARENTID",Const.news.news.getId()).orderBy("sort"));
		return Result.ok(dicts.parallelStream().map( dict -> {
			Map<String,Object> bean = BeanUtil.beanToMap(dict);
			bean.put("classify", dict.getId());
			return bean;}).collect(Collectors.toList()));
	} 
	
	@Override
	public Result<?> newsHelp(String userId) {
		DictDO dict = sysDictService.selectById(Const.help.help_help.getId());
		return Result.ok(BeanUtil.beanToMap(dict));
	} 
	
	@Override
	public Result<?> newsAboutOurs(String userId) {
		DictDO dict = sysDictService.selectById(Const.help.help_about_ours.getId());
		return Result.ok(BeanUtil.beanToMap(dict));
	}
	private String sql = "ID,TITLE,SHOWPICTURES,SOURCE,APPROVAL,CLICKRATE,USEABLE,TOP,CATEGORY,CLASSIFY,VERIFY,SOURCETYPE,ENTRYTYPE,CREATE_TIME,CREATE_ID,SORT,UPDATE_ID,VERIFYTIME,VIDEOZHUANMA,ZUOZHE,BIANJI,LIANJIE,URL,LOCATION,VIDEOAUTHOR,UPDATETIME,VIDEOPATH,VIDEOPICTUREPATH,ZHUANMA,SHOWVIDEO,UPDATE_TIME,USER_ID,TOP_DEPT_ID,DELFLAG,NIAN,YUE,RI,COLLECT,DW_CODE";
	@Override
	public PageResult<?> pageList(String userId, String dwCode,String title,String classify, String nian, String yue, String ri,
			Page<News> page) {
		if(StringUtils.isBlank(dwCode) || dwCode.length() < Const.dwCodeSubLength){ 
			PageResult<?> pageR = new PageResult<>();
			pageR.setPageNum(1);
			pageR.setHasNext(false);
			return pageR;
	    } 
		//返回数据进行拼装 
	    return  data2Page(userId,this.selectPage(page, new EntityWrapper<News>().setSqlSelect(sql)
	    		.like("DW_CODE", dwCode.substring(0, Const.dwCodeSubLength), SqlLike.RIGHT)
	    		.or()
	    		.eq("DW_CODE", dwCode.substring(0, Const.dwCodeSubLength / 2))
	    		.andNew()
	    		.ne("CLASSIFY", Const.help.help_about_ours.getId())
	    		.ne("CLASSIFY", Const.help.help_agreement.getId())
	    		.ne("CLASSIFY", Const.help.help_help.getId())
	    		.eq("VERIFY",2) 
	    		.eq("DELFLAG",0)
	    		.eq(StringUtils.isNotBlank(classify),"CLASSIFY", classify) 
		    	.eq(StringUtils.isNotBlank(nian),"NIAN",nian)
		    	.eq(StringUtils.isNotBlank(yue),"YUE",yue)
		    	.eq(StringUtils.isNotBlank(ri),"RI",ri)
		    	.orderBy("TOP")
		    	.orderBy("NIAN",false)
		    	.orderBy("YUE",false)
		    	.orderBy("RI",false).orderBy("CREATE_TIME",false)));
	}
	
	@Override
	public PageResult<?> pageHelpList(String userId, String dwCode,String title,String classify, String nian, String yue, String ri,
			Page<News> page) {
		if(StringUtils.isBlank(dwCode) || dwCode.length() < Const.dwCodeSubLength){ 
			PageResult<?> pageR = new PageResult<>();
			pageR.setPageNum(1);
			pageR.setHasNext(false);
			return pageR;
	    } 
		//返回数据进行拼装 
	    return  data2Page(userId,this.selectPage(page, new EntityWrapper<News>()
	    		.eq("DW_CODE", dwCode.substring(0, Const.dwCodeSubLength/2))
	    		.eq("VERIFY",2) 
	    		.eq("DELFLAG",0)
	    		.eq(StringUtils.isNotBlank(classify),"CLASSIFY", classify) 
		    	.eq(StringUtils.isNotBlank(nian),"NIAN",nian)
		    	.eq(StringUtils.isNotBlank(yue),"YUE",yue)
		    	.eq(StringUtils.isNotBlank(ri),"RI",ri)
		    	.orderBy("TOP")
		    	.orderBy("NIAN",false)
		    	.orderBy("YUE",false)
		    	.orderBy("RI",false).orderBy("CREATE_TIME",false)));
	}
	/**
	 * 将查询的信息 进行拼装
	 * */
	private  PageResult<?> data2Page(String userId,Page<News> pageAll){
		PageResult<Map<String,Object>> pageRes = new PageResult<>(); 
		if(CollectionUtil.isEmpty(pageAll.getRecords())){ 
			PageResult<?> pageR = new PageResult<>();
			pageR.setPageNum(1);
			pageR.setHasNext(false);
			return pageR;
	    } 
		List<Map<String,Object>> lmap = Lists.newArrayList();
		pageAll.getRecords().stream().forEach(version ->{ 
			if(StringUtils.isBlank(version.getUrl())){
				version.setUrl(httpPath+"/img/a1.jpg");
         	}
//			if(StringUtils.isNotBlank(version.getContent())){
//				version.setContent(StringEscapeUtils.escapeHtml(version.getContent()));
//			} 
			Map<String,Object> map = BeanUtil.beanToMap(version);
			map.put("newsId",version.getId());
			lmap.add(map);
		});
		pageRes.setListData(lmap);
		pageRes.setPageNum(pageAll.getCurrent());
		pageRes.setHasNext(pageAll.hasNext());
		return pageRes; 
	}
	
	@Override
	public Result<?> info(String userId,String newsId) {
		News news = this.selectOne(new EntityWrapper<News>(News.builder().id(newsId).build()));
		if(news == null)
			return Result.fail_msg("此新闻以丢失");
		//更新点击量
		news.setClickrate(news.getClickrate()+1);
		this.updateById(news);
		news.setZContent("<!DOCTYPE html><html lang='zh-CN'><head><meta charset='utf-8' /><meta name='referrer' content='no-referrer'><style>img{max-width:320px !important;}</style></head><body>"+StringUtils.replace(news.getContent(), "&amp", "")+"</body></html>");
		return Result.ok(BeanUtil.beanToMap(news));
	}
	
	@Override
	public Result<?> collect(String userId,String newsId) {
		News news = this.selectOne(new EntityWrapper<News>(News.builder().id(newsId).build()));
		if(news == null)
			return Result.fail_msg("此新闻以丢失");
		//更新点击量
		news.setCollect(news.getCollect() + 1);
		this.updateById(news); 
		Calendar calendar = Calendar.getInstance(); 
		collectMapper.insert(NewsCollect.builder().nian(calendar.get(Calendar.YEAR)).yue(calendar.get(Calendar.MONTH)+1).ri(calendar.get(Calendar.DAY_OF_MONTH)).newsId(newsId).userId(userId).build());
		
		return Result.ok(BeanUtil.beanToMap(news));
	}
	
	@Override
	public Result<?> unCollect(String userId,String newsId) {
		News news = this.selectOne(new EntityWrapper<News>(News.builder().id(newsId).build()));
		if(news == null)
			return Result.fail_msg("此新闻以丢失");
		//更新点击量
		news.setCollect(news.getCollect() - 1);
		this.updateById(news); 
		collectMapper.delete(new EntityWrapper<NewsCollect>(NewsCollect.builder().userId(userId).newsId(newsId).build()));
		
		return Result.ok(BeanUtil.beanToMap(news));
	}
	
	@Override
	public Result<?> click(String userId,String newsId) {
		News news = this.selectOne(new EntityWrapper<News>(News.builder().id(newsId).build()));
		if(news == null)
			return Result.fail_msg("此新闻以丢失");
		//更新点赞量
		news.setApproval(news.getApproval()+1);
		this.updateById(news);  
		return Result.ok(BeanUtil.beanToMap(news));
	}
	
	@Override
	public Result<?> unClick(String userId,String newsId) {
		News news = this.selectOne(new EntityWrapper<News>(News.builder().id(newsId).build()));
		if(news == null)
			return Result.fail_msg("此新闻以丢失");
		//更新点赞量
		news.setApproval(news.getApproval()-1);
		this.updateById(news);  
		return Result.ok(BeanUtil.beanToMap(news));
	}
	@Override
	public Result<?> remove(String id) {
		if(StringUtils.isBlank(id) )
			return Result.fail_msg("缺少必要参数"); 
		
		News news = this.selectById(id);
		if(news == null)
			return Result.fail_msg("新闻不存在");  
		
		return this.updateById(news.setDelflag(1))?Result.ok() : Result.fail();
	}

	@Override
	public Result<?> batchRemove(List<String> ids) {
		if(CollectionUtil.isEmpty(ids))
			return Result.fail_msg("缺少必要参数"); 
		
		List<News> newsList = this.selectBatchIds(ids);
		if(CollectionUtil.isEmpty(newsList))
			return Result.fail_msg("新闻不存在"); 
		
		newsList.parallelStream().forEach(news -> news.setDelflag(1));
		 
		return this.updateBatchById(newsList) ? Result.ok():Result.fail();
	}

	@Override
	public Result<?> add(HttpServletRequest request,String userId, String dwCode, News news) throws IOException{ 
		//上传图片
		UploadResult result = UploadUtils.uploadOssPic(request);
		if(CollectionUtil.isNotEmpty(result.getFileURLs())){ 
			news.setUrl(result.getFileURLs().get(0));
		} 
		if(StringUtils.isNotBlank(news.getVideopath())){ 
			String suffx = StrUtil.subAfter(StrUtil.subBetween(news.getVideopath(),".", "?"), ".", true);
			news.setZhuanma(suffx.equals("mp4")?Const.transCode.success_trans.getValue():Const.transCode.need_trans.getValue());
		}
		
		
		if(StringUtils.isNotBlank(news.getId())){
			News oldNews = this.selectById(news.getId());
			if(oldNews == null){
				return Result.fail_msg("新闻不存在");
			}
			//上传新图片，同时删除老图片
			if(StringUtils.isNotBlank(news.getUrl()) && StringUtils.isNotBlank(oldNews.getUrl())){
				UploadUtils.deletePic(oldNews.getUrl());
			}
			BeanUtil.copyProperties(news, oldNews);
			return this.updateById(oldNews) ? Result.ok():Result.fail();
		}
		Calendar calendar = Calendar.getInstance();
		news.setNian(calendar.get(Calendar.YEAR)).setYue(calendar.get(Calendar.MONTH)+1).setRi(calendar.get(Calendar.DAY_OF_MONTH));
		news.setApproval(0).setClickrate(0).setCollect(0).setVerify(2).setSourcetype(2);
		//新闻来源
		news.setSource(sysDeptService.selectOne(new EntityWrapper<DeptDO>().eq("DW_CODE", dwCode)).getName());
		return this.insert(news.setUserId(userId).setDelflag(0).setDwCode(dwCode))? Result.ok():Result.fail();
	}
	
	@Override
	public com.ifast.common.utils.Result<?> transCode(String newsId) {
		 
		if (newsId == null) { 
			return com.ifast.common.utils.Result.fail("参数为空");
		}
		News news = this.selectById(newsId);
		if (news == null || StringUtils.isBlank(news.getVideopath())) {
			return com.ifast.common.utils.Result.fail("参数为空");
		}
		SubmitJobsRequest submitJobsRequest = new SubmitJobsRequest();
		// 输入源
		JSONObject inputObject = new JSONObject();
		inputObject.put("Bucket", OSSMtsUtil.BUCKETNAME);
		inputObject.put("Location", OSSMtsUtil.LOCATION);
		// 是否包含？ 
		String videoSou = news.getVideopath();
		if (StrUtil.containsIgnoreCase(videoSou, "?")
				&& StrUtil.containsIgnoreCase(videoSou, OSSMtsUtil.ALIYUN_URL)) {
			videoSou = StrUtil.split(videoSou, OSSMtsUtil.ALIYUN_URL)[1];
			inputObject.put("Object", StrUtil.split(videoSou, "?")[0]);
		} else {
			inputObject.put("Object", videoSou);
		}
		String input = inputObject.toJSONString();
		// 输出源
		JSONObject outputObject = new JSONObject();
		Random random = new Random();
		String videoTo = UploadUtils.createSaveURLAli("/news/video")+"/" + random.nextInt(10000) + System.currentTimeMillis() + ".mp4";
		String picTo = UploadUtils.createSaveURLAli("/news/pic")+"/" + random.nextInt(10000) + System.currentTimeMillis() + ".jpg";
		
		outputObject.put("OutputObject", videoTo);
		outputObject.put("TemplateId", OSSMtsUtil.TEMPLETID);
		JSONArray outputArrs = new JSONArray();
		outputArrs.add(outputObject);
		String outputs = outputArrs.toJSONString();
		// 封装请求
		submitJobsRequest.setInput(input);
		submitJobsRequest.setOutputs(outputs);
		submitJobsRequest.setPipelineId(OSSMtsUtil.PIPELINEId);
		submitJobsRequest.setOutputBucket(OSSMtsUtil.BUCKETNAME);
		submitJobsRequest.setOutputLocation(OSSMtsUtil.LOCATION);
		try {
			SubmitJobsResponse submitJobsResponse = OSSMtsUtil.getClient()
					.getAcsResponse(submitJobsRequest);
			List<JobResult> list = submitJobsResponse.getJobResultList();
			if (CollectionUtil.isNotEmpty(list)) {
				List<String> jobIdList = Lists.newArrayList();
				for (JobResult temp : list) {
					if (temp.getSuccess()) {
						jobIdList.add(temp.getJob().getJobId());
					}
				}
				// 请求是否上传ok
				if (list.size() == jobIdList.size()) {
					String jobIds = Joiner.on(",").skipNulls().join(jobIdList);
					boolean flagJ = this.zhuanmaJingDu(jobIds);
					boolean retFlag = savePicPathAndUpdateForNews(news,flagJ, videoTo, picTo);
					if (!retFlag) {
						return com.ifast.common.utils.Result.fail("转码失败!"); 
					}
				}
			}
		} catch (ServerException e) {
			e.printStackTrace();
			return com.ifast.common.utils.Result.fail("转码失败!"); 
			 
		} catch (Exception e) {
			e.printStackTrace();
			return com.ifast.common.utils.Result.fail("转码失败!"); 
			 
		}
		return com.ifast.common.utils.Result.ok(); 
	} 
	// 获取转码进度
	public boolean zhuanmaJingDu(String jobIds) {
		boolean flag = true;
		boolean flagRet = false;
		if (StrUtil.isBlank(jobIds)) {
			return flag;
		}
		while (flag) {
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			QueryJobListRequest queryJobListRequest = new QueryJobListRequest();
			queryJobListRequest.setJobIds(jobIds);
			try {
				QueryJobListResponse queryJobListResponse = OSSMtsUtil
						.getClient().getAcsResponse(queryJobListRequest);
				List<Job> listJobs = queryJobListResponse.getJobList();
				// 目前只有一个任务
				if (CollectionUtil.isEmpty(listJobs)) {
					flag = false;
					return flagRet;
				}
				Job job = listJobs.get(0);
				//log.info("转码进度状态" + job.getState());
				if (Objects.equal("TranscodeFail", job.getState())) {
					flag = false;
					return flagRet;
				}
				
				if (Objects.equal(100L, job.getPercent())) {
					flag = false;
					flagRet = true;
					return flagRet;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return flagRet;
	}
	// 获取图片地址和跟新数据
		 
	public boolean savePicPathAndUpdateForNews(News news, boolean flagJ,
			String videoTo, String picTo) {
		Map<String, String> mapDizhi = this.getPicPathAndUpdateCommen(flagJ,videoTo, picTo);
		try {
			if (mapDizhi != null) {
				news.setVideopicturepath(mapDizhi.get("tupiandizhi"));
				news.setZhuanma(Const.transCode.success_trans.getValue()); 
				// 跟新数据
				news.setVideopath(mapDizhi.get("shipindizhi")); 
				this.updateById(news); 
				return true;
			} else { 
				news.setZhuanma(Const.transCode.fail_trans.getValue());  
				this.updateById(news); 
				return false;
			}
		} catch (Exception e) { 
			e.toString();
		}
		return false;
	}

	// 获取截图和视频地址的公共方法
	public Map<String, String> getPicPathAndUpdateCommen(boolean flagJ,
			String videoTo, String picTo) {
		Map<String, String> map = null;
		// 进度判断
		if (flagJ) {
			// 去截屏
			boolean flagJu = this.jietuPicForNews(picTo, videoTo);
			if (flagJu) {
				map = Maps.newHashMap();
				OSSBjOtherClientUtil oSSBjClientUtil = new OSSBjOtherClientUtil();
				String videoToPath = oSSBjClientUtil.getUrlFile(videoTo);
				videoToPath = OSSMtsUtil.ALIYUN_URL
						+ StrUtil.split(videoToPath, OSSMtsUtil.ALIYUN_URL)[1];
				String picToPath = oSSBjClientUtil.getUrlFile(picTo);
				log.info("视屏地址" + videoToPath);
				log.info("图片地址" + picToPath);
				map.put("shipindizhi", videoToPath);
				map.put("tupiandizhi", picToPath);
			}
			return map;
		} else {
			return map;
		}
	}
	/**
	 * 截图
	 * 
	 * @param picTo
	 * @param videoSou
	 * @return
	 */ 
	public boolean jietuPicForNews(String picTo, String videoSou) {
		boolean flag = false;
		// 输入
		JSONObject inputObject = new JSONObject();
		inputObject.put("Bucket", OSSMtsUtil.BUCKETNAME);
		inputObject.put("Location", OSSMtsUtil.LOCATION);
		inputObject.put("Object", videoSou);
		String input = inputObject.toJSONString();
		// 输出
		JSONObject snapshotConfigObject = new JSONObject();
		JSONObject outputFile = new JSONObject();
		outputFile.put("Bucket", OSSMtsUtil.BUCKETNAME);
		outputFile.put("Location", OSSMtsUtil.LOCATION);
		outputFile.put("Object", picTo);
		snapshotConfigObject.put("OutputFile", outputFile);
		snapshotConfigObject.put("Time", 50000); // 50000毫秒之后视屏的截图
		snapshotConfigObject.put("Num", 1); // 几张
		String snapshotConfig = snapshotConfigObject.toJSONString();
		// 处理
		SubmitSnapshotJobRequest snapshotJobRequest = new SubmitSnapshotJobRequest();
		snapshotJobRequest.setInput(input);
		snapshotJobRequest.setSnapshotConfig(snapshotConfig);
		snapshotJobRequest.setPipelineId(OSSMtsUtil.PIPELINEId);
		try {
			SubmitSnapshotJobResponse snapshotJobResponse = OSSMtsUtil
					.getClient().getAcsResponse(snapshotJobRequest);
			SnapshotJob snapshotJob = snapshotJobResponse.getSnapshotJob();
			log.info("截取图片返回结果 : " + snapshotJob.getState());
			flag = true;
		} catch (ServerException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return flag;
	}
}